<!--
  上传组件（向后端服务器获取表单形式， 直传到oss）

  @author will
  @site https://pt.jdyd.xyz
  @date 2022/01/14 12:14
-->
<template>
  <div style="">
    <a-upload
      v-model:fileList="vdata.fileList"
      name="uploadFile"
      :customRequest="uploadImage"
      :beforeUpload="beforeUploadFunc"
      :headers="vdata.headers"
      :data="vdata.formParams"
      list-type="picture"
      :showUploadList="props.showUploadList"
      :multiple="false"
      :accept="vdata.accept"
      :disabled="props.disabled"
      @preview="previewFileFunc"
      @change="handleChange"
    >
      <slot v-if=" !props.showUploadList || vdata.fileList.length <= 0" name="uploadBtn">
        <a-button type="primary"><upload-outlined />点 击 上 传</a-button>
      </slot>
      <template #itemRender="{ file, actions }" />
    </a-upload>
  </div>
</template>

<script setup lang="ts">
import axios from 'axios'
import { reactive,defineProps, getCurrentInstance, onMounted, watch } from 'vue'
import { $getUploadFormParams} from '@/api/manage'
import { sm4DecryptByResData } from '@/utils/encryptUtil'
import { shrinkImage } from 'shrinkpng'
const { $infoBox, $viewerApi } = getCurrentInstance()!.appContext.config.globalProperties

// 定义 父组件传参
const props = defineProps ({
    showUploadList: { type: Boolean, default: true }, // 是否显示上传的列表， 一般都需要显示，  比如头像需要自定义的话那么则不需要显示，并且按钮常显
    src: { type: String, default: '' }, // 双向绑定  文件地址
    bizType: { type: String, default : ''}, // 业务类型
    fileType: { type: String, default: 'img' }, // img or file 
    accept: { type: String, default: null }, // 上传文件的accept
    ocrType: {type: String, default: null }, // orc类型如果存在值则上传成功后自动调起ORC识别功能
    disabled: { type: Boolean, default: false }, // 是否禁用
    size: { type: Number, default: 2 }, // 图片限制大小,单位M
})

  // 父组件通讯函数
const emit = defineEmits(['update:src', 'change', 'ocrScan'])

// 定义响应式数据 
const vdata : any = reactive({
    action: '',  // 文件form表单请求地址 
    fileList: [], // 全部文件集合
    formParams: {}, // 上传参数
    headers: {}, // 放入token
    formReqFileUrl: '', // 第一次的form请求的图片数据， 如果存在则使用该地址， 否则使用文件上传的响应地址。 
    accept: null, //上传文件的accept

    ysFile:null
})

onMounted(() => {
 if(props.src){
   vdata.fileList = [{ url: props.src, name: getFileName(props.src) }]
 }
 // 处理 accept
 if(!props.accept && props.fileType == 'img'){
    vdata.accept = 'image/*' // 所有的图片格式
 }else{
   vdata.accept = props.accept
 }
})

// // 监听变化
watch( () => props.src ,(newVal, oldVal)=>{
  if (newVal) {
    vdata.fileList = [{ url: newVal, name: getFileName(newVal) }]
  }else{
   vdata.fileList = []
  }
})

function getFileName(name){
  if(!name){
    return name
  }
  return name.substring(name.lastIndexOf('/') + 1)
}

  // 上传回调
function handleChange (info) {
  if (!info.file.status) {
    vdata.fileList = []
    return
  }
  if (info.file.status === 'uploading') {
    return
  }
  if (info.file.status === 'done') { // 上传完成
    vdata.fileList = [] // 通过watch 更改文件集合
    // 如果包含code 并且 不是0 ： 本系统返回的错误信息。 
    if(info.file.response.code &&  info.file.response.code != 0 ){
      return $infoBox.message.error(info.file.response.msg)
    }
    // 上传成功
    let successImgUrl = vdata.formReqFileUrl
    // 读取响应结果的值
    if(!successImgUrl){
      successImgUrl = info.file.response.encryptData ? sm4DecryptByResData(info.file.response.encryptData) : info.file.response.data 
    }
    emit('update:src', successImgUrl)
    emit('change', successImgUrl)
  } else if (info.file.status === 'error') { // 上传异常
    vdata.fileList = []
    $infoBox.message.error('上传异常,请联系系统管理员')
  } else if (info.file.status === 'removed') { // 文件被删除 
    vdata.formReqFileUrl = ''
    emit('update:src', vdata.formReqFileUrl)
    emit('change', vdata.formReqFileUrl)
  }

}
// 上传图片前的校验
async function beforeUploadFunc (file) {
  // 压缩图片
  let _file
  if(props.fileType == 'img'){
    _file = await shrinkImage(file,{quality:30})
  }else{
    _file = file
  }
  vdata.ysFile = _file

  // 校验图片大小
  if (_file && _file.size > props.size * 1024 * 1024) {
    var msg = '单张图片请不超过' + props.size + 'MB'
    $infoBox.message.error(msg)
    return false
  }
  return $getUploadFormParams(_file, props.bizType).then(res => {
    vdata.action = res.formActionUrl // action 
    vdata.formParams = res.formParams //表单组件 
    vdata.formReqFileUrl = res.ossFileUrl
  })
}

// 自定义上传图片
function uploadImage(e){
  let dataFile = new FormData()
  for (const key in vdata.formParams) {
    dataFile.append(key,vdata.formParams[key])
  }
  dataFile.append('file',vdata.ysFile)
  vdata.fileList = [] // 通过watch 更改文件集合
  axios.request({
    url:vdata.action,
    method:'POST',
    transformRequest:[function(data,headers){
      delete headers.post['Content-Type']
      return dataFile
    }],
    data:vdata.ysFile
  }).then(res=>{
    if(res.status==200||res.status==204){
      // 上传成功
      let successImgUrl = vdata.formReqFileUrl
      emit('update:src', successImgUrl)
      emit('change', successImgUrl)
    }
  })
}

// 预览图片
function previewFileFunc(file){
  if(props.fileType == 'img'){
    $viewerApi({images: [props.src]})
  }
}


</script>
<style scoped lang="less">

/deep/ .ant-upload-list-item-name {
  flex: auto !important
}

</style>